using System;
using System.Collections.Generic;
using System.Resources;
using System.Windows.Forms;
using Infragistics.UltraChart.Data.Series;
using Infragistics.UltraChart.Resources.Appearance;
using PluginFrame;

namespace PcrDataAnalysis
{
    public class AlleleAnalysis
    {
        protected IConfigurationService mConfigurationService;

        private IPcrExperimentProject mProject;

        private double[] mPointAngle;

        private List<IAlleleAnalysisParameterConfiguration> mAnalysisOption;

        private List<double[]> mData;

        private List<int> mCellIndex;

        private IProjectItem[] mAvailableProjectItem = new IProjectItem[2];

        private XYSeries[] mAlleleDataSeries;

        private XYSeries mNegativeUndeterminedSeries;

        private List<int> mNegativeUndeterminedCellIndex;

        private List<int>[] mAlleleCellIndex;

        private string[] mAlleleTypeString;

        private IAlleleExperiment mAlleleExperiment;

        private string[] mAlleleTargets;

        protected ResourceManager mResourceManager;

        protected string[] mDetectionTypes;

        protected List<string> mErrorString;

        protected bool mIsSeriesCellNA;

        protected int mProjectIndex;

        private double CalculateAngle(double y, double x)
        {
            double num = Math.Atan(y / x);
            if (x < 0.0)
            {
                num += Math.PI;
            }
            return num;
        }

        public AlleleAnalysis(IApplication application, IPcrExperimentProject project, int projectIndex, IAlleleExperiment alleleExperiment)
        {
            mProject = project;
            mAlleleDataSeries = new XYSeries[Enum.GetNames(typeof(AlleleCallResult)).GetLength(0)];
            mAlleleCellIndex = new List<int>[mAlleleDataSeries.Length];
            string[] names = Enum.GetNames(typeof(AlleleCallResult));
            for (int i = 0; i < mAlleleDataSeries.Length; i++)
            {
                mAlleleDataSeries[i] = new XYSeries();
                mAlleleDataSeries[i].Label = names[i];
                mAlleleCellIndex[i] = new List<int>();
            }
            mNegativeUndeterminedSeries = new XYSeries();
            mNegativeUndeterminedCellIndex = new List<int>();
            mAlleleTargets = alleleExperiment.GetAlleleItemTargets(projectIndex);
            if (projectIndex == 0)
            {
                alleleExperiment.FirstAvailableChannelIndex = 5;
            }
            mAlleleExperiment = alleleExperiment;
            mResourceManager = ResourceManager.CreateFileBasedResourceManager("PcrDataAnalysis", application.GetResourceFolder() + GetType().Namespace + "\\", null);
            mConfigurationService = (IConfigurationService)application.GetService("ConfigurationService");
            mDetectionTypes = mConfigurationService.GetDetectionTypeArray(PcrSystemType.Allele);
        }

        public AnalysisError Execute()
        {
            mPointAngle = new double[3]
            {
                0.0,
                Math.PI / 4.0,
                Math.PI / 2.0
            };
            int num = 0;
            IProjectItem[] projectItems = mProject.ProjectItems;
            foreach (IProjectItem projectItem in projectItems)
            {
                if (projectItem != null && !string.IsNullOrEmpty(projectItem.Name) && projectItem.ChannelConfiguration.IsSelected && projectItem.ChannelConfiguration.IsAvailable)
                {
                    if (mAlleleExperiment.FirstAvailableChannelIndex > projectItem.ChannelConfiguration.Position)
                    {
                        mAlleleExperiment.FirstAvailableChannelIndex = projectItem.ChannelConfiguration.Position;
                    }
                    mAvailableProjectItem[num++] = projectItem;
                    if (num >= mAvailableProjectItem.Length)
                    {
                        break;
                    }
                }
            }
            if (num != mAvailableProjectItem.Length)
            {
                return AnalysisError.AlleleError;
            }
            mAlleleTargets[0] = mAvailableProjectItem[0].Name;
            mAlleleTargets[1] = mAvailableProjectItem[1].Name;
            mAlleleTypeString = new string[6];
            mAlleleTypeString[0] = mAvailableProjectItem[0].Name + "/" + mAvailableProjectItem[0].Name;
            mAlleleTypeString[1] = mAvailableProjectItem[0].Name + "/" + mAvailableProjectItem[1].Name;
            mAlleleTypeString[2] = mAvailableProjectItem[1].Name + "/" + mAvailableProjectItem[1].Name;
            mAlleleTypeString[3] = mResourceManager.GetString("AlleleStandardString");
            mAlleleTypeString[4] = mResourceManager.GetString("AlleleUndeterminedString");
            mAlleleTypeString[5] = mResourceManager.GetString("AlleleNegativeString");
            mAnalysisOption = new List<IAlleleAnalysisParameterConfiguration>(2);
            for (int j = 0; j < mAvailableProjectItem.Length; j++)
            {
                IAlleleAnalysisParameterConfiguration alleleAnalysisParameterConfiguration = mAvailableProjectItem[j].TubeAnalysisParameterConfiguration[0] as IAlleleAnalysisParameterConfiguration;
                if (alleleAnalysisParameterConfiguration == null)
                {
                    return AnalysisError.AlleleError;
                }
                mAnalysisOption.Add(alleleAnalysisParameterConfiguration);
            }
            mIsSeriesCellNA = false;
            mErrorString = new List<string>();
            Calculate();
            GenerateResult();
            if (mIsSeriesCellNA)
            {
                string text = string.Empty;
                foreach (string item in mErrorString)
                {
                    text = text + item + "\r\n";
                }
                MessageBox.Show(text, mResourceManager.GetString("ErrorString"));
                return AnalysisError.AlleleError;
            }
            return AnalysisError.NA;
        }

        private void InitializeSerieDataPoints()
        {
            mData = new List<double[]>();
            mCellIndex = new List<int>();
            int position = mAvailableProjectItem[0].ChannelConfiguration.Position;
            for (int i = 0; i < mProject.Cells.Count; i++)
            {
                mProject.Cells[i].InitializeAllelePointSeries();
                if (mProject.Cells[i].IsBad)
                {
                    mProject.Cells[i].SetCellInformation("MethodKey", position, "N/A");
                    mProject.Cells[i].SetCellInformation("CallKey", position, "N/A");
                    mProject.Cells[i].SetCellInformation("QualityKey", position, "N/A");
                    mData.Add(null);
                    mCellIndex.Add(mProject.Cells[i].CellID);
                    continue;
                }
                double[] array = new double[mAvailableProjectItem.Length];
                for (int j = 0; j < mAvailableProjectItem.Length; j++)
                {
                    int position2 = mAvailableProjectItem[j].ChannelConfiguration.Position;
                    int dataIndex = mProject.Cells[i].GetAmplificationCurvePointCount(position2) - 1;
                    array[j] = mProject.Cells[i].GetCurveLightData(position2, dataIndex);
                }
                string cellInformation = mProject.Cells[i].GetCellInformation("DetectionTypeKey", position);
                if (cellInformation.Equals(mDetectionTypes[2]))
                {
                    if (array[1] < mAnalysisOption[1].ManualThreshold && array[0] < mAnalysisOption[0].ManualThreshold)
                    {
                        mAlleleDataSeries[5].Points.Add(new XYDataPoint(array[0], array[1], mProject.Cells[i].CellID.ToString(), false));
                        mAlleleCellIndex[5].Add(i);
                    }
                    else
                    {
                        mNegativeUndeterminedSeries.Points.Add(new XYDataPoint(array[0], array[1], mProject.Cells[i].CellID.ToString(), false));
                        mNegativeUndeterminedCellIndex.Add(i);
                    }
                    mData.Add(null);
                }
                else
                {
                    mData.Add(array);
                }
                mCellIndex.Add(mProject.Cells[i].CellID);
                int position3 = mAvailableProjectItem[0].ChannelConfiguration.Position;
                int position4 = mAvailableProjectItem[1].ChannelConfiguration.Position;
                mProject.Cells[i].SetCellInformation("Rn1Key", position3, array[0].ToString("0.000"));
                mProject.Cells[i].SetCellInformation("Rn2Key", position3, array[1].ToString("0.000"));
                mProject.Cells[i].SetCellInformation("Rn1Key", position4, array[1].ToString("0.000"));
                mProject.Cells[i].SetCellInformation("Rn2Key", position4, array[0].ToString("0.000"));
            }
        }

        private int FindNearestAngle(XYDataPoint point)
        {
            double num = CalculateAngle(point.ValueY, point.ValueX);
            double num2 = double.PositiveInfinity;
            int result = 0;
            for (int i = 0; i < mPointAngle.Length; i++)
            {
                double num3 = Math.Abs(num - mPointAngle[i]);
                if (num3 < num2)
                {
                    num2 = num3;
                    result = i;
                }
            }
            return result;
        }

        private double[] CalculateCenter(XYDataPointCollection dataList)
        {
            if (dataList == null || dataList.Count == 0)
            {
                return null;
            }
            double num = 0.0;
            double num2 = 0.0;
            foreach (XYDataPoint data in dataList)
            {
                num += data.ValueX;
                num2 += data.ValueY;
            }
            return new double[2]
            {
                num / (double)dataList.Count,
                num2 / (double)dataList.Count
            };
        }

        private void Calculate()
        {
            mPointAngle = new double[3]
            {
                0.0,
                Math.PI / 4.0,
                Math.PI / 2.0
            };
            int[] array = new int[mPointAngle.Length];
            int num = 0;
            int num2 = 0;
            bool flag = false;
            double gainRatio = mAnalysisOption[0].GainRatio;
            InitializeSerieDataPoints();
            do
            {
                for (int i = 0; i < mAlleleDataSeries.Length - 1; i++)
                {
                    mAlleleDataSeries[i].Points.Clear();
                    mAlleleCellIndex[i].Clear();
                }
                for (int j = 0; j < mData.Count; j++)
                {
                    if (mData[j] == null)
                    {
                        continue;
                    }
                    int position = mAvailableProjectItem[0].ChannelConfiguration.Position;
                    if (mData[j][0] < mAnalysisOption[0].ManualThreshold && mData[j][1] < mAnalysisOption[1].ManualThreshold)
                    {
                        string cellInformation = mProject.Cells[j].GetCellInformation("DetectionTypeKey", position);
                        if (!cellInformation.Equals(mDetectionTypes[2]))
                        {
                            mAlleleDataSeries[4].Points.Add(new XYDataPoint(mData[j][0], mData[j][1], mProject.Cells[j].CellID.ToString(), false));
                            mAlleleCellIndex[4].Add(j);
                        }
                    }
                    else
                    {
                        double valueX = mData[j][0];
                        double num3 = mData[j][1];
                        num3 *= gainRatio;
                        XYDataPoint point = new XYDataPoint(valueX, num3, mCellIndex[j].ToString(), false);
                        int num4 = FindNearestAngle(point);
                        mAlleleDataSeries[num4].Points.Add(point);
                        mAlleleCellIndex[num4].Add(j);
                    }
                }
                num = 0;
                for (int k = 0; k < 3; k++)
                {
                    if (array[k] == mAlleleDataSeries[k].Points.Count)
                    {
                        num++;
                    }
                    else
                    {
                        array[k] = mAlleleDataSeries[k].Points.Count;
                    }
                }
                if (num2 < 10 && num != mPointAngle.Length)
                {
                    flag = false;
                    for (int l = 0; l < 3; l++)
                    {
                        double[] array2 = CalculateCenter(mAlleleDataSeries[l].Points);
                        if (array2 != null && (!(array2[0] < 0.0) || !(array2[1] < 0.0)))
                        {
                            mPointAngle[l] = CalculateAngle(array2[1], array2[0]);
                        }
                    }
                }
                else
                {
                    flag = true;
                }
            }
            while (!flag);
        }

        private void GenerateResult()
        {
            double gainRatio = mAnalysisOption[0].GainRatio;
            int position = mAvailableProjectItem[0].ChannelConfiguration.Position;
            for (int i = 0; i < mNegativeUndeterminedSeries.Points.Count; i++)
            {
                mAlleleDataSeries[4].Points.Add(mNegativeUndeterminedSeries.Points[i]);
                mAlleleCellIndex[4].Add(mNegativeUndeterminedCellIndex[i]);
            }
            for (int j = 0; j < mAlleleDataSeries.Length; j++)
            {
                bool flag = false;
                if (mAlleleDataSeries[j].Points.Count == 0)
                {
                    mAlleleDataSeries[j].Points.Add(new XYDataPoint(-1.0, -1.0, "", true));
                }
                else
                {
                    int num = 0;
                    string text = string.Empty;
                    double num2 = double.NaN;
                    bool flag2 = false;
                    AlleleCallResult alleleCallResult = (AlleleCallResult)Enum.Parse(typeof(AlleleCallResult), mAlleleDataSeries[j].Label);
                    if (alleleCallResult != AlleleCallResult.Negative && alleleCallResult != AlleleCallResult.Undetermined)
                    {
                        num2 = 0.0;
                        foreach (XYDataPoint point in mAlleleDataSeries[j].Points)
                        {
                            num2 += CalculateAngle(point.ValueY, point.ValueX);
                        }
                        num2 /= (double)mAlleleDataSeries[j].Points.Count;
                    }
                    else if (alleleCallResult == AlleleCallResult.Undetermined)
                    {
                        flag2 = true;
                    }
                    if (mAnalysisOption[0].AlleleAnalysisType == AlleleAnalysisType.StandardGroup)
                    {
                        List<string> list = new List<string>();
                        foreach (XYDataPoint point2 in mAlleleDataSeries[j].Points)
                        {
                            XYDataPoint xYDataPoint = point2;
                            int num3 = mAlleleCellIndex[j][num++];
                            if (num3 >= mProject.Cells.Count)
                            {
                                continue;
                            }
                            IPcrCell pcrCell = mProject.Cells[num3];
                            bool flag3 = pcrCell.CellPosition == "H4";
                            string cellInformation = pcrCell.GetCellInformation("DetectionTypeKey", position);
                            if (cellInformation.Equals(mDetectionTypes[0]))
                            {
                                list.Add(pcrCell.CellPosition);
                                if (string.IsNullOrEmpty(text))
                                {
                                    text = pcrCell.GetCellInformation("PropertyKey", position);
                                }
                                else
                                {
                                    flag = true;
                                }
                            }
                        }
                        if (flag)
                        {
                            GenerateAlleleStandardCellErrorString(list);
                        }
                        else
                        {
                            for (int k = j + 1; k <= 2; k++)
                            {
                                if (k == j)
                                {
                                    continue;
                                }
                                for (int l = 0; l < mAlleleDataSeries[k].Points.Count; l++)
                                {
                                    int num4 = mAlleleCellIndex[k][l];
                                    if (num4 >= mProject.Cells.Count)
                                    {
                                        continue;
                                    }
                                    IPcrCell pcrCell2 = mProject.Cells[num4];
                                    if (!pcrCell2.IsBad)
                                    {
                                        string cellInformation2 = pcrCell2.GetCellInformation("DetectionTypeKey", position);
                                        if (cellInformation2.Equals(mDetectionTypes[0]) && text.Equals(pcrCell2.GetCellInformation("PropertyKey", position)))
                                        {
                                            list.Add(pcrCell2.CellPosition);
                                            flag = true;
                                        }
                                    }
                                }
                            }
                            if (flag)
                            {
                                GenerateAlleleStandardCellErrorString(list);
                            }
                        }
                    }
                    num = 0;
                    foreach (XYDataPoint point3 in mAlleleDataSeries[j].Points)
                    {
                        int num5 = mAlleleCellIndex[j][num];
                        if (num5 >= mProject.Cells.Count)
                        {
                            continue;
                        }
                        IPcrCell pcrCell3 = mProject.Cells[num5];
                        if (pcrCell3 != null)
                        {
                            point3.Label = Enum.Parse(typeof(AlleleCallResult), j.ToString()).ToString();
                            pcrCell3.AlleleSeries[0].Points.Add(point3);
                            double num6 = 0.0;
                            string value = string.Empty;
                            double num7 = double.NaN;
                            string value2 = string.Empty;
                            string empty = string.Empty;
                            if (!flag)
                            {
                                if (!num2.Equals(double.NaN))
                                {
                                    flag2 = false;
                                    num7 = CalculateAngle(point3.ValueY, point3.ValueX);
                                    num6 = 1.0 - Math.Abs(num7 - num2);
                                    if (num6 < 0.0)
                                    {
                                        num6 = 0.0;
                                    }
                                    if (num6 < mAnalysisOption[0].QualityFactor)
                                    {
                                        point3.Label = AlleleCallResult.Undetermined.ToString();
                                        flag2 = true;
                                    }
                                    else
                                    {
                                        value = num6.ToString("0.000");
                                    }
                                }
                                if (flag2)
                                {
                                    empty = mAlleleTypeString[4];
                                }
                                else if (mAnalysisOption[0].AlleleAnalysisType == AlleleAnalysisType.AutoGroup || string.IsNullOrEmpty(text))
                                {
                                    empty = mAlleleTypeString[j];
                                    if (alleleCallResult != AlleleCallResult.Negative)
                                    {
                                        value2 = mResourceManager.GetString("AutoGroupString");
                                    }
                                }
                                else
                                {
                                    empty = text;
                                    value2 = mResourceManager.GetString("StandardGroupString");
                                }
                            }
                            else
                            {
                                empty = "N/A";
                            }
                            point3.ValueY /= gainRatio;
                            for (int m = 0; m < mAvailableProjectItem.Length; m++)
                            {
                                int position2 = mAvailableProjectItem[m].ChannelConfiguration.Position;
                                pcrCell3.SetCellInformation("MethodKey", position2, value2);
                                pcrCell3.SetCellInformation("CallKey", position2, empty);
                                pcrCell3.SetCellInformation("QualityKey", position2, value);
                            }
                        }
                        num++;
                    }
                }
                mIsSeriesCellNA |= flag;
            }
        }

        private void GenerateAlleleStandardCellErrorString(List<string> stdCellPosition)
        {
            string text = mResourceManager.GetString("AlleleStandardString") + "(";
            for (int i = 0; i < stdCellPosition.Count; i++)
            {
                text = text + stdCellPosition[i] + ",";
            }
            text = text.Substring(0, text.Length - 1);
            text = text + ")" + mResourceManager.GetString("StandardConflictingString");
            if (!mErrorString.Contains(text))
            {
                mErrorString.Add(text);
            }
        }
    }
}
